﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Drawing;
using System.Threading;

namespace Smled
{
    public class TileMap
    {
        private Tile[,] map;
        private int width, height;
        private TileSet mSet;
        private System.Drawing.Color mBackColor = System.Drawing.Color.Blue;

        public TileMap(int TheWidth, int TheHeight)
        {
            width = TheWidth;
            height = TheHeight;
            map = new Tile[width, height];
        }

        public bool SaveToFile(string FileName)
        {
            return SaveToFile(FileName, System.Drawing.Color.Blue);
        }

        public Tile GetTileAt(int x, int y)
        {
            if (x >= 0 && x < width && y >= 0 && y < height) return map[x, y];
            return null;
        }

        public void SetTileAt(int x, int y, Tile t)
        {
            if (x >= 0 && x < width && y >= 0 && y < height) map[x, y] = t;
        }

        public bool LoadFromFile(string FileName)
        {
            if (!File.Exists(FileName)) return false;
            Thread.Sleep(1000);

            try
            {
                TileSet ts = new TileSet(FileName);

                libACO.ACOarchive arc = new libACO.ACOarchive(FileName);

                FileStream fs = arc.GetFileStream("map.dat");

                StreamReader sr = new StreamReader(fs);


                int r = sr.Read();
                int g = sr.Read();
                int b = sr.Read();
                mBackColor = System.Drawing.Color.FromArgb(r, g, b);

                char[] s = new char[2];

                sr.Read(s, 0, 2);
                width = ((int)s[0] * 256 + (int)s[1]);
                sr.Read(s, 0, 2);
                height = ((int)s[0] * 256 + (int)s[1]);

                map = new Tile[width, height];

                for (int y = 0; y < height; ++y)
                {
                    for (int x = 0; x < width; ++x)
                    {
                        int t = sr.Read();
                        map[x, y] = ts.GetTile(t);
                    }
                }

                sr.Close();
                fs.Close();

                mSet = ts;
            }
            catch (Exception)
            {
                return false;
            }

            return true;
        }

        public bool SaveToFile(string FileName, System.Drawing.Color BackColor)
        {
            if (mSet == null) return false;

            mSet.SaveToFile(FileName);

            string tmpFolder = Path.GetTempPath();
            StreamWriter sw = new StreamWriter(tmpFolder + "\\map.dat");

            sw.Write(new char[] { (char)mBackColor.R, (char)mBackColor.G, (char)mBackColor.B });
            sw.Write(new char[] { (char)(width / 256), (char)(width % 256)});
            sw.Write(new char[] { (char)(height / 256), (char)(height % 256) });

            for (int y = 0; y < height; ++y)
            {
                for (int x = 0; x < width; ++x)
                {
                    sw.Write((char)((map[x, y] == null) ? 255 : map[x, y].ID));
                }
            }

            sw.Close();

            List<string> mapList = new List<string>();
            mapList.Add(tmpFolder + "\\map.dat");
            libACO.libACOAux.ImpAddFiles(FileName, mapList);

            return true;
        }

        public int Width
        {
            get { return width; }
        }

        public int Height
        {
            get { return height; }
        }

        public Tile[,] Map
        {
            get { return map; }
        }

        public TileSet Set
        {
            get { return mSet; }
            set { mSet = value; }
        }

        public System.Drawing.Color BackColor
        {
            get { return mBackColor; }
            set { mBackColor = value; }
        }

        public string GetArrayString()
        {
            string txt = "(";
            for (int y = 0; y < height; ++y)
            {
                txt += "[";
                for (int x = 0; x < width; ++x)
                {
                    if (map[x, y] != null)
                    {
                        txt += map[x, y].ID.ToString();
                    }
                    else
                    {
                        txt += "0";
                    }

                    if (x < width - 1)
                    {
                        txt += ",";
                    }
                }
                txt += "]";
                if (y < height - 1)
                {
                    txt += ",";
                }
            }
            txt += ")";
            return txt;
        }

        public string GetArrayStringBBall(int startX, int startY)
        {
            string txt = "" + width + "\n" + height + "\n" + (startX + 1) + "\n" + (startY + 1) + "\ntiletest1.bmp\nbacktest.bmp\n";
            
            for (int y = 0; y < height; ++y)
            {
                for (int x = 0; x < width; ++x)
                {
                    if (map[x, y] != null)
                    {
                        switch (map[x, y].ID)
                        {
                            case 0: txt += "B"; break;
                            case 1: txt += "B"; break;
                            case 2: txt += "3"; break;
                            case 3: txt += "u"; break;
                            case 4: txt += "r"; break;
                            case 5: txt += "d"; break;
                            case 6: txt += "l"; break;
                            case 7: txt += "U"; break;
                            case 8: txt += "R"; break;
                            case 9: txt += "D"; break;
                            case 10: txt += "L"; break;
                            case 11: txt += "z"; break;
                            case 12: txt += "x"; break;
                            case 13: txt += "c"; break;
                            case 14: txt += "v"; break;
                            case 15: txt += "*"; break;
                            default: txt += "."; break;
                        }
                    }
                    else
                    {
                        txt += ".";
                    }
                }
                txt += "\n";
            }
            return txt;
        }

        public void Resize(int nWidth, int nHeight)
        {
            Resize(nWidth, nHeight, ContentAlignment.TopLeft);
        }

        public void Resize(int nWidth, int nHeight, ContentAlignment Alignment)
        {
            if (nWidth < 1 || nWidth > 500 || nHeight < 1 || nHeight > 500) return;

            int offX = 0, offY = 0;
            switch (Alignment)
            {
                case ContentAlignment.TopLeft:
                    offX = 0;
                    offY = 0;
                    break;
                case ContentAlignment.TopCenter:
                    offX = (nWidth - width) / 2;
                    offY = 0;
                    break;
                case ContentAlignment.TopRight:
                    offX = nWidth - width;
                    offY = 0;
                    break;
                case ContentAlignment.MiddleLeft:
                    offX = 0;
                    offY = (nHeight - height) / 2;
                    break;
                case ContentAlignment.MiddleCenter:
                    offX = (nWidth - width) / 2;
                    offY = (nHeight - height) / 2;
                    break;
                case ContentAlignment.MiddleRight:
                    offX = nWidth - width;
                    offY = (nHeight - height) / 2;
                    break;
                case ContentAlignment.BottomLeft:
                    offX = 0;
                    offY = nHeight - height;
                    break;
                case ContentAlignment.BottomCenter:
                    offX = (nWidth - width) / 2;
                    offY = nHeight - height;
                    break;
                case ContentAlignment.BottomRight:
                    offX = nWidth - width;
                    offY = nHeight - height;
                    break;
            }

            Tile[,] nMap = new Tile[nWidth, nHeight];

            for (int x = 0; x < nWidth; ++x)
            {
                for (int y = 0; y < nHeight; ++y)
                {
                    if (x - offX > 0 && x - offX < width && y - offY > 0 && y - offY < height)
                    {
                        nMap[x, y] = map[x - offX, y - offY];
                    }
                    else
                    {
                        nMap[x, y] = null;
                    }
                }
            }

            map = nMap;
            width = nWidth;
            height = nHeight;
        }
    }
}
